<?php

class ChatroomModel
{
    private $chatroomModelKeyPrefix               =   'CR/';
    private $chatroomMemberModelKeyPrefix         =   'CM/';
    private $chatroomQuestionModelKeyPrefix       =   'CQ/';
    
    private $diaryListCacheModel;
    private $autoUidModel;
    private $hashByUidType = 0;
    private $hashByRidType = 1;
    
    function __construct()/*{{{*/
    {
        $this->diaryListCacheModel  =   new DiaryListCacheModel();
        $this->autoUidModel         =   new AutoUidModel();
    }
    
    /**
     * 创建聊天室
     * @param unknown $uid
     * @param unknown $param
     * @return boolean
     */
    public function createChatroom($uid, $param){
        if (empty($uid) || empty($param)) {
            AC::$errorNo = 'CRM001';
            return false;
        }
        
        $data   =   array(
            'name'        =>  UK::getstr($param['name'], 24),
            'intro'       =>  UK::getstr($param['content'], 150),
            'uid'         =>  $uid,
            'cover'       =>  $param['cover'],
            'p_num'       =>  0,
            'max_p_num'   =>  AC::CHAT_ROOM_MAX_P,
            'category'    =>  intval($param['category']),
            'status'      =>  0,
            'type'        =>  1,
            'time'        =>  AC::SERVER_TIME,
            'dateline'    =>  AC::SERVER_TIME + AC::DEFAULT_CHAT_ROOM_EXPIRE,
            'display'     =>  0
        );
        
        $key    =   $this->chatroomModelKeyPrefix. 0;
        $result =   Storage::addData($key, $data);
        if (empty($result)){
            AC::$errorNo = 'CRM002';
            return false;
        }
        
        // 加入缓存
        $this->addChatRoomToCategoryList($result, $data['category'], $data['dateline']);
        
        return $result;
    }
    
    /**
     * 编辑聊天室
     */
    public function modifyChatRoom($rid, $param){
        if (empty($rid) || empty($param)) {
            AC::$errorNo = 'CRM001';
            return false;
        }
        
        $data = $this->assembleChatroomDataOfMysql($param, 'edit');
        if (empty($data)) return false;

        $key    =   $this->chatroomModelKeyPrefix. 0;
        $where = array('id' => $rid, 'status' => 0);
        $result = Storage::setConditionData($key, $data, $where);
        if (empty($result)){
            AC::$errorNo = 'CRM002';
            return false;
        } 

        if ($data['status'] > 0) {
            $this->delChatRoomDataOfRedis($rid);
            $this->delChatRoomSetOfRedis($rid);
        }else{
            $this->setChatRoomDataOfRedis($rid, $data);
        }
        
        return $result;
    }
    
    /**
     * 获取了聊天室详情
     * @param unknown $rid
     * @return multitype:|Ambigous <multitype:, unknown, boolean>
     */
    public function getChatRoomInfo ($rid) {
        if (empty($rid)) return array();
        
        $result = $this->getChatRoomDataOfRedis($rid);
        if (empty($result) || count($result) < 5) {
            $key    =   $this->chatroomModelKeyPrefix. 0;
            $where = array('id' => $rid, 'status' => 0);
            $result = Storage::getConditionData($key, $where);
            if ($result) {
                $this->setChatRoomDataOfRedis($rid, $result);
            }
        }
        
        return $result;
    }
    
    /**
     * 增加人数
     * @param unknown $rid
     * @return Ambigous <multitype:, boolean, Ambigous>
     */
    public function increaseChatRoomPepleNumber ($rid) {
        return $this->setChatRoomNumber($rid, array('p_num' => 1));
    }
    
    /**
     * 减少人数
     * @param unknown $rid
     * @return Ambigous <multitype:, boolean, Ambigous>
     */
    public function reduceChatRoomPepleNumber ($rid) {
        return $this->setChatRoomNumber($rid, array('p_num' => -1));
    }
    
    /**
     * 聊天室成员数增减
     * @param unknown $rid
     * @param unknown $data
     * @return multitype:|boolean|Ambigous <boolean, number, resource>
     */
    public function setChatRoomNumber ($rid, $param) {
        if (empty($rid) || empty($param)) {
            AC::$errorNo    =   'CRM001';
            return  FALSE;
        }
        
        $data = array();
        isset($param['p_num'])    && $data['p_num']  = $param['p_num'];// 此处值为1 或 -1
        if (empty($data)) return false;
        
        $key    =   $this->chatroomModelKeyPrefix. 0;
        $where  =   array('id' => $rid, 'status' => 0);
        $result =   Storage::changeNumValueAdd($key, $data, $where);
        if (empty($result)){
            AC::$errorNo    =   'CRM002';
            return  FALSE;
        }
        
        $this->updateChatRoomMembersOfRedis($rid, 'p_num', $data['p_num']);
        return $result;
    }
    
    /**
     * 解散聊天室
     * @param unknown $rid
     * @return Ambigous <multitype:, boolean, Ambigous>
     */
    public function disbandChatRoom ($rid) {
        $data = array('status' => 1);
        return $this->modifyChatRoom($rid, $data);
    }
    
    /**
     * 组装聊天室数据结构
     * @param unknown $param
     * @param string $type
     * @return multitype:string number unknown NULL
     */
    private function assembleChatroomDataOfMysql ($param, $type = 'edit') {
        $data = array();
        isset($param['uid'])         &&  $data['uid']           =   intval($param['uid']);
        isset($param['category'])    &&  $data['category']      =   intval($param['category']);
        isset($param['qid'])         &&  $data['qid']           =   intval($param['qid']);
        isset($param['p_num'])       &&  $data['p_num']         =   intval($param['p_num']);
        isset($param['max_p_num'])   &&  $data['max_p_num']     =   intval($param['max_p_num']);
        isset($param['status'])      &&  $data['status']        =   intval($param['status']);
        isset($param['type'])        &&  $data['type']          =   intval($param['type']);
        isset($param['dateline'])    &&  $data['dateline']      =   intval($param['dateline']);
        isset($param['question_id']) &&  $data['question_id']   =   intval($param['question_id']);
        isset($param['display'])     &&  $data['display']       =   intval($param['display']);
        isset($param['name'])        &&  $data['name']          =   UK::getstr($param['name'], 24);
        isset($param['content'])     &&  $data['intro']         =   UK::getstr($param['content'], 150);
        isset($param['cover'])       &&  $data['cover']         =   UK::getstr($param['cover'], 250);
        isset($param['extras'])      &&  $data['extras']        =   $param['extras'];
        
        if ($type === 'add') {
            $data['time'] = AC::SERVER_TIME;
        }
        
        return $data;
    }
    
    /**
     * 获取聊天室列表
     * @param unknown $id
     * @param unknown $start
     * @param unknown $length
     * @return Ambigous <unknown, boolean, multitype:>
     */
    public function getChatRooms($category, $id, $start, $length) {
        $result = $this->getChatRoomListByCategory($category, $start, $length);
        if (empty($result) && $id < 1) {
            $key    =   $this->chatroomModelKeyPrefix. 0;
            $where  =   " `status` = 0 AND `category` = ".$category." AND `dateline` >= ".AC::SERVER_TIME;
            if ($id > 0) {
                $where = " `status` = 0 AND `category` = ".$category." AND id < ".$id." AND `dateline` >= ".AC::SERVER_TIME;
            }
            $order  =   'id DESC';
            $result =   Storage::getConditionManyData($key,$where,$order,$start,$length);

            $this->rebuildChatRooms($category);
        }
        
        return  $result;
    }
    
    private function rebuildChatRooms ($category) {
        $key    =   $this->chatroomModelKeyPrefix. 0;
        $where  =   " `status` = 0 AND `category` = ".$category." AND `dateline` >= ".AC::SERVER_TIME;
        
        $order  =   'id DESC';
        $result =   Storage::getConditionManyData($key,$where,$order);
        if ($result) {
            foreach ($result as $value) {
                if ($value['dateline'] > AC::SERVER_TIME) {
                    $this->addChatRoomToCategoryList($value['id'], $value['category'], $value['dateline']);
                }
            }
        }
        
        return true;
    }
    
    private function sliceChatRooms ($list, $length) {
        shuffle($list);
        $list = array_slice($list, 0, $length);

        if ($list) {
            foreach ($list as &$value) {
                if (count($value) == 1) {
                    $value = $this->getChatRoomInfo($value);
                }
            }
        }
        
        return $list;
    }
    
    /**
     * 获取用户当前所在的聊天室列表
     * @param unknown $uid
     * @return Ambigous <multitype:, unknown, boolean>
     */
    public function getUserChatrooms ($uid) {
        $key    =   $this->chatroomMemberModelKeyPrefix . $uid;
        $where  =   array('uid' => $uid, 'type' => $this->hashByUidType, 'status' => AC::CHAT_ROOM_PASS_STATUS);
        $result =   Storage::getConditionManyData($key, $where);
        return $result;
    }
    
    /**
     * 获取用户与聊天室信息
     * @param unknown $uid
     * @param unknown $rid
     * @return Ambigous <multitype:, unknown, boolean>
     */
    public function getUserChatRoomInfo ($uid, $rid) {
        $key    =   $this->chatroomMemberModelKeyPrefix. $uid;
        $where  =   array('uid' => $uid, 'rid' => $rid, 'type' => $this->hashByUidType);
        $result =   Storage::getConditionData($key, $where);
        return  $result;
    }
    
    /**
     * 获取聊天室所有用户
     * @param unknown $rid
     * @return Ambigous <multitype:, unknown, boolean>
     */
    public function getChatroomMembers ($rid) {
        $uids = $this->getUsersFromChatRoomOfRedis($rid);
        if (empty($uids)) {
            $key    =   $this->chatroomMemberModelKeyPrefix . $rid;
            $where  =   array('rid' => $rid, 'status' => AC::CHAT_ROOM_PASS_STATUS, 'type' => $this->hashByRidType);
            $orderBy=   " role DESC ";
            $result =   Storage::getConditionManyData($key, $where, $orderBy);
            if ($result) {
                foreach ($result as $value) {
                    $this->addUserToChatRoomOfRedis($rid, $value['uid'], $value['active_time'] ? $value['active_time'] : AC::SERVER_TIME);
                }
            }
        }else{
            $result = $this->getChatRoomUsersByUids($uids, $rid);
        }
        
        return $result;
    }
    
    private function getChatRoomUsersByUids ($uids, $rid) {
        if (empty($uids)) return array();
        
        $result = array();
        foreach ($uids as $value) {
            $result[] = $this->getUserChatRoomInfo($value, $rid);
        }
        return $result;
    }
    
    /**
     * 创建用户与聊天室的关系
     * @param unknown $uid
     * @param unknown $rid
     * @return boolean
     */
    public function addUserToChatroomMember ($uid, $rid, $role) {
        if (empty($uid) || empty($rid)) {
            AC::$errorNo = 'CRM001';
            return false;
        }
        
        // 组装数据
        $data   =   array(
            'rid'         =>  $rid,
            'uid'         =>  $uid,
            'type'        =>  $this->hashByUidType,
            'status'      =>  AC::CHAT_ROOM_PASS_STATUS,
            'role'        =>  $role,
            'active_time' =>  AC::SERVER_TIME,
            'create_time' =>  AC::SERVER_TIME
        );
        
        // 以uid分表
        $key    =   $this->chatroomMemberModelKeyPrefix. $uid;
        $result =   $this->addChatroomMember($key, $data);
        if(empty($result)) return  FALSE;
        
        // 以rid分表
        $data['type'] = $this->hashByRidType;
        $key    =   $this->chatroomMemberModelKeyPrefix. $rid;
        $result =   $this->addChatroomMember($key, $data);
        if(empty($result)) return  FALSE;
        
        // 同步缓存数据
        $this->increaseChatRoomPepleNumber($rid);
        $this->addUserToChatRoomOfRedis($rid, $uid, AC::SERVER_TIME);
        
        return  true;
    }
    
    /**
     * 添加用户与聊天室的关系进数据库
     * @param unknown $key
     * @param unknown $data
     * @return boolean
     */
    private function addChatroomMember($key, $data){
        if (empty($key) || empty($data)) return false;
        
        $result =   Storage::addData($key, $data);
        if (empty($result)){
            AC::$errorNo = 'CRM002';
            return false;
        }
        
        return  $result;
    }
    
    public function setUserToChatroomMember ($uid, $rid) {
        if (empty($uid) || empty($rid)) {
            AC::$errorNo = 'CRM001';
            return false;
        }

        $where = array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByUidType );
        // 组装数据
        $data   =   array(
            'status'      =>  AC::CHAT_ROOM_PASS_STATUS,
            'active_time' =>  AC::SERVER_TIME
        );

        // 以uid分表
        $key    =   $this->chatroomMemberModelKeyPrefix. $uid;
        $result =   $this->setChatroomMember($key, $data, $where);
        if(empty($result)) return  FALSE;
    
        // 以rid分表
        $where = array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByRidType);
        $data['type'] = $this->hashByRidType;
        $key    =   $this->chatroomMemberModelKeyPrefix. $rid;
        $result =   $this->setChatroomMember($key, $data, $where);
        if(empty($result)) return  FALSE;
	   
        // 同步缓存
        $this->addUserToChatRoomOfRedis($rid, $uid, AC::SERVER_TIME);
        $this->increaseChatRoomPepleNumber($rid);
        
        return  true;
    }
    
    /**
     * 退出聊天室
     * @param unknown $uid
     * @param unknown $rid
     * @return boolean
     */
    public function quitChatroomMember($uid, $rid) {
        if (empty($uid) || empty($rid)) {
            AC::$errorNo = 'CRM001';
            return false;
        }
        
        
        // 组装数据
        $data   =   array('status' =>  AC::CHAT_ROOM_QUIT_STATUS);
        $where  =   array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByUidType);
        
        // 以uid分表
        $key    =   $this->chatroomMemberModelKeyPrefix. $uid;
        $result =   $this->setChatroomMember($key, $data, $where);
        if(empty($result)) return  FALSE;
        
        $where  =   array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByRidType);
        $key    =   $this->chatroomMemberModelKeyPrefix. $rid;
        $result =   $this->setChatroomMember($key, $data, $where);
        if(empty($result)) return  FALSE;
        
        // 更新缓存、减少人数
        $inChatRoom = $this->checkUserIsInChatRoom($rid, $uid);
        if ($inChatRoom) {
            $this->delUserFromChatRoomOfRedis($rid, $uid);
            $this->reduceChatRoomPepleNumber($rid);
        }
        
        return true;
    }
    
    /**
     * 更新用户活跃时间
     * @param unknown $uid
     * @param unknown $rid
     * @return boolean
     */
    public function setUserActive ($uid, $rid) {
        if (empty($uid) || empty($rid)) {
            return false;
        }
        
        $inChatRoom = $this->checkUserIsInChatRoom($rid, $uid);
        if ($inChatRoom) {
            $this->setUserActiveOfRedis($rid, $uid, AC::SERVER_TIME);
        
            // 组装数据
            $data   =   array('active_time' =>  AC::SERVER_TIME);
            $where  =   array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByUidType);
            
            // 以uid分表
            $key    =   $this->chatroomMemberModelKeyPrefix. $uid;
            $result =   $this->setChatroomMember($key, $data, $where);
            if(empty($result)) return  false;
            
            $where  =   array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByRidType);
            $key    =   $this->chatroomMemberModelKeyPrefix. $rid;
            $result =   $this->setChatroomMember($key, $data, $where);
            if(empty($result)) return  false;
        }
        
        return true;
    }
    
    public function fireUserFromChatRoom($uid, $rid) {
        if (empty($uid) || empty($rid)) {
            AC::$errorNo = 'CRM001';
            return false;
        }
        
        // 组装数据
        $data   =   array('status' =>  AC::CHAT_ROOM_FIRE_STATUS);
        $where  =   array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByUidType);
        
        // 以uid分表
        $key    =   $this->chatroomMemberModelKeyPrefix. $uid;
        $result =   $this->setChatroomMember($key, $data, $where);
        if(empty($result)) return  FALSE;
    
        $where  =   array('uid' => $uid, 'rid' => $rid, 'type' =>  $this->hashByRidType);
        $key    =   $this->chatroomMemberModelKeyPrefix. $rid;
        $result =   $this->setChatroomMember($key, $data, $where);
        if(empty($result)) return  FALSE;
        
        // 更新缓存及计数
        $inChatRoom = $this->checkUserIsInChatRoom($rid, $uid);
        if ($inChatRoom) {
            $this->delUserFromChatRoomOfRedis($rid, $uid);
            $this->reduceChatRoomPepleNumber($rid);
        }
        
        return true;
    }
    
    /**
     * 更新memeber数据
     * @param unknown $key
     * @param unknown $data
     * @param unknown $where
     * @return boolean|Ambigous <boolean, unknown, number, resource>
     */
    private function setChatroomMember($key, $data, $where){
        if (empty($key) || empty($data) || empty($where)) return false;
	
        $result =   Storage::setConditionData($key, $data, $where);
        if (empty($result)){
            AC::$errorNo = 'CRM002';
            return false;
        }
        
        return  $result;
    }
    
    public function setChatRoomUsersStatus($rid){
        for($i=0; $i<=7; $i++) {
            $sql        =   "Update xxtlike.chatroom_member_".$i." SET status = ".AC::CHAT_ROOM_QUIT_STATUS." WHERE rid = ".$rid;
            $keyClient  =   $this->chatroomMemberModelKeyPrefix. $i;
            $result     =   Storage::fetchDbSentenceByClient($keyClient, $sql, 2);
        }
        
        return  true;
    }
    
    //=============================================缓存========================================
    
    public function getChatRoomListByCategory ($category, $start = 0, $length = 20) {
        if (empty($category)) {
            return false;
        }
        
        $list = $this->diaryListCacheModel->getChatRoomListByCategory($category, AC::SERVER_TIME + AC::DEFAULT_CHAT_ROOM_EXPIRE, AC::SERVER_TIME);
        if ($list) {
            $list = $this->sliceChatRooms($list, $length);
        }
        
        return $list;
    }
    
    public function addChatRoomToCategoryList ($rid, $category, $dateline) {
        if (empty($rid) || empty($category) || empty($dateline)) {
            return false;
        }
        
        return $this->diaryListCacheModel->addChatRoomToCategoryList($rid, $category, $dateline);
    }
    
    public function delChatRoomFromCategoryList ($rid, $category) {
        if (empty($rid) || empty($category)) {
            return false;
        }
        
        return $this->diaryListCacheModel->delChatRoomFromCategoryList($rid, $category);
    }        

    /**
     * 获取聊天室信息
     * @param unknown $rid
     */
    public function getChatRoomDataOfRedis ($rid) {
        if (empty($rid)) {
            return false;
        }
    
        return $this->diaryListCacheModel->getChatRoomData($rid);
    }
    
    /**
     * 更新聊天室信息
     * @param unknown $rid
     */
    public function setChatRoomDataOfRedis ($rid, $data) {
        if (empty($rid) || empty($data)) {
            return false;
        }
    
        return $this->diaryListCacheModel->setChatRoomData($rid, $data);
    }
    
    /**
     * 删除聊天室
     * @param unknown $rid
     */
    public function delChatRoomDataOfRedis ($rid) {
        if (empty($rid)) {
            return false;
        }
    
        return $this->diaryListCacheModel->delChatRoomData($rid);
    }
    
    /**
     * 更新聊天室计数
     * @param unknown $rid
     * @param unknown $field
     * @param number $num
     */
    public function updateChatRoomMembersOfRedis ($rid, $field, $num) {
        if (empty($rid) || empty($field)) {
            return false;
        }
    
        return $this->diaryListCacheModel->updateChatRoomMembers($rid, $field, $num);
    }
    
    /**
     * 添加用户到聊天室成员列表
     * @param unknown $rid
     * @param unknown $uid
     * @param unknown $time
     */
    public function addUserToChatRoomOfRedis ($rid, $uid, $time) {
        if (empty($rid) || empty($uid) || empty($time)) {
            return false;
        }
    
        return $this->diaryListCacheModel->addUserToChatRoom($rid, $uid, $time);
    }
    
    public function getChatRoomUserCount ($rid) {
        if (empty($rid)) {
            return false;
        }
    
        return $this->diaryListCacheModel->getChatRoomUserCount($rid);
    }
    
    /**
     * 获取用户列表
     * @param unknown $rid
     * @return boolean
     */
    public function getUsersFromChatRoomOfRedis ($rid) {
        if (empty($rid)) {
            return false;
        }
    
        return $this->diaryListCacheModel->getUsersFromChatRoom($rid);
    }
    
    public function checkUserIsInChatRoom ($rid, $uid) {
        if (empty($rid) || empty($uid)) {
            return false;
        }
    
        $result =  $this->getUserScoreFromChatRoom($rid, $uid);
        if (empty($result)) return false;
    
        return true;
    }
    
    public function getUserScoreFromChatRoom($rid, $uid) {
        return $this->diaryListCacheModel->getUserScoreFromChatRoom($rid, $uid);
    }
    
    /**
     * 更新聊天室用户活跃时间
     * @param unknown $rid
     * @param unknown $uid
     * @param unknown $time
     */
    public function setUserActiveOfRedis ($rid, $uid, $time) {
        if (empty($rid) || empty($uid) || empty($time)) {
            return false;
        }
    
        return $this->diaryListCacheModel->setUserActive($rid, $uid, $time);
    }
    
    /**
     * 从聊天室中移除用户
     * @param unknown $rid
     * @param unknown $uid
     */
    public function delUserFromChatRoomOfRedis ($rid, $uid) {
        if (empty($rid) || empty($uid)) {
            return false;
        }
    
        return $this->diaryListCacheModel->delUserFromChatRoom($rid, $uid);
    }
    
    /**
     * 删除聊天室用户列表缓存
     * @param unknown $rid
     * @return boolean
     */
    public function delChatRoomSetOfRedis ($rid) {
        if (empty($rid)) {
            return false;
        }
    
        return $this->diaryListCacheModel->delChatRoomSet($rid);
    }
    
}